const Oi = {};

export default class Dep {
  // Dep 不仅是订阅者 他订阅后还要收集watcher来更新模板 所以Dep也可以说是发布者
  constructor() {
    this.watcher = [];
  }
  // target 表示Watch
  static target = null;

  depend() {
    // 如果已经存在就不收集
    if (this.watcher.includes(Dep.target)) return;
    this.watcher.push(Dep.target);
    if (!Oi[window.$keyert]) {
      Oi[window.$keyert] = [];
    }
    Oi[window.$keyert].push(this.watcher);
    // console.log('this.watcher ====> ', this.watcher, this.watcher[0]._Uid)
    // for (const item of this.watcher) {
    //   console.log("item===> ", item._cb);
    // }
  }

  // 通知依赖 watcher 更新
  notify() {
    debugger;
    this.watcher.forEach((sub) => {
      sub.update();
    });
  }
}

Dep.target = null;
const targetStack = [];
// 存储所有的 Dep.target
// 为什么会有多个 Dep.target?
// 组件会产生一个渲染 Watcher，在渲染的过程中如果处理到用户 Watcher，
// 比如 computed 计算属性，这时候会执行 evalute -> get
// 假如直接赋值 Dep.target，那 Dep.target 的上一个值 —— 渲染 Watcher 就会丢失
// 造成在 computed 计算属性之后渲染的响应式数据无法完成依赖收集
/**
 * 备份本次传递进来的 Watcher，并将其赋值给 Dep.target
 * @param {*} target Watcher 实例
 */
export function pushTarget(target) {
  targetStack.push(target);
  Dep.target = target;
}

// 会在 Dep 执行完watcher后执行，要移除掉已经执行完的
export function popTarget() {
  targetStack.pop();
  Dep.target = targetStack[targetStack.length - 1];
  // console.log("targetStack ====> ", targetStack, Dep.target);
}
